package org.coinor.opents.net;

import org.coinor.opents.*;
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.rmi.*;
import java.rmi.server.*;


public class ClusterApp extends javax.swing.JFrame 
{

    /** Creates new form ClusterApp */
    public ClusterApp() 
    {
        super();
        initComponents();
        initPostForteComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents()//GEN-BEGIN:initComponents
    {
        clusterController = new org.coinor.opents.net.ClusterController();
        clientTableModel = new org.coinor.opents.net.ClientTabuSearchTableModel();
        pnlHost = new javax.swing.JPanel();
        lblTSName = new javax.swing.JLabel();
        lblTSNameValue = new javax.swing.JLabel();
        lblInitClass = new javax.swing.JLabel();
        txtInitClass = new javax.swing.JTextField();
        btnClassBrowse = new javax.swing.JButton();
        lblIterations = new javax.swing.JLabel();
        pnlIterations = new javax.swing.JPanel();
        txtIterations = new javax.swing.JTextField();
        progIterations = new javax.swing.JProgressBar();
        pnlHostButtons = new javax.swing.JPanel();
        btnStartStop = new javax.swing.JButton();
        lblInitStatus = new javax.swing.JLabel();
        lblCodebase = new javax.swing.JLabel();
        txtCodebase = new javax.swing.JTextField();
        btnBrowseCodebase = new javax.swing.JButton();
        pnlAdvanced = new javax.swing.JPanel();
        lblUDPPortNumber = new javax.swing.JLabel();
        txtUDPPortNumber = new javax.swing.JTextField();
        lblHTTPPortNumber = new javax.swing.JLabel();
        txtHTTPPortNumber = new javax.swing.JTextField();
        tglAdvanced = new javax.swing.JToggleButton();
        lblAdvanced = new javax.swing.JLabel();
        pnlClients = new javax.swing.JPanel();
        scrClients = new javax.swing.JScrollPane();
        tblClients = new javax.swing.JTable();
        
        clusterController.start();
        clusterController.addClusterControllerListener(new org.coinor.opents.net.ClusterControllerListener()
        {
            public void clientAdded(org.coinor.opents.net.ClusterControllerEvent evt)
            {
            }
            public void clientRemoved(org.coinor.opents.net.ClusterControllerEvent evt)
            {
            }
            public void clientPropertyChanged(org.coinor.opents.net.ClusterControllerEvent evt)
            {
            }
            public void tabuSearchStarted(org.coinor.opents.net.ClusterControllerEvent evt)
            {
                clusterControllerTabuSearchStarted(evt);
            }
            public void tabuSearchStopped(org.coinor.opents.net.ClusterControllerEvent evt)
            {
            }
        });
        
        
        getContentPane().setLayout(new java.awt.GridBagLayout());
        java.awt.GridBagConstraints gridBagConstraints1;
        
        setTitle(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("clusterapp.frame.title"));
        addWindowListener(new java.awt.event.WindowAdapter()
        {
            public void windowClosing(java.awt.event.WindowEvent evt)
            {
                exitForm(evt);
            }
        });
        
        pnlHost.setLayout(new java.awt.GridBagLayout());
        java.awt.GridBagConstraints gridBagConstraints2;
        
        pnlHost.setBorder(new javax.swing.border.TitledBorder(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.border.title")));
        lblTSName.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.label.tsname.text"));
        lblTSName.setEnabled(false);
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 1;
        gridBagConstraints2.gridy = 1;
        gridBagConstraints2.insets = new java.awt.Insets(1, 1, 1, 1);
        gridBagConstraints2.anchor = java.awt.GridBagConstraints.WEST;
        pnlHost.add(lblTSName, gridBagConstraints2);
        
        lblTSNameValue.setFont(new java.awt.Font("Dialog", 0, 12));
        lblTSNameValue.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.label.tsnamevalue.text"));
        lblTSNameValue.setEnabled(false);
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 2;
        gridBagConstraints2.gridy = 1;
        gridBagConstraints2.gridwidth = 2;
        gridBagConstraints2.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints2.insets = new java.awt.Insets(1, 1, 1, 1);
        gridBagConstraints2.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints2.weightx = 1.0;
        pnlHost.add(lblTSNameValue, gridBagConstraints2);
        
        lblInitClass.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.label.classname.text"));
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 1;
        gridBagConstraints2.gridy = 4;
        gridBagConstraints2.insets = new java.awt.Insets(1, 1, 1, 1);
        pnlHost.add(lblInitClass, gridBagConstraints2);
        
        txtInitClass.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.textfield.classname.text"));
        txtInitClass.addFocusListener(new java.awt.event.FocusAdapter()
        {
            public void focusLost(java.awt.event.FocusEvent evt)
            {
                txtInitClassFocusLost(evt);
            }
        });
        
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 2;
        gridBagConstraints2.gridy = 4;
        gridBagConstraints2.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints2.insets = new java.awt.Insets(1, 1, 1, 1);
        gridBagConstraints2.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints2.weightx = 1.0;
        pnlHost.add(txtInitClass, gridBagConstraints2);
        
        btnClassBrowse.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.button.class-browse.text"));
        btnClassBrowse.setEnabled(false);
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 3;
        gridBagConstraints2.gridy = 4;
        gridBagConstraints2.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints2.insets = new java.awt.Insets(1, 1, 1, 1);
        pnlHost.add(btnClassBrowse, gridBagConstraints2);
        
        lblIterations.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.label.iterations.text"));
        lblIterations.setToolTipText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.label.iterations.tooltip"));
        lblIterations.setLabelFor(txtIterations);
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 1;
        gridBagConstraints2.gridy = 2;
        gridBagConstraints2.insets = new java.awt.Insets(1, 1, 1, 1);
        gridBagConstraints2.anchor = java.awt.GridBagConstraints.WEST;
        pnlHost.add(lblIterations, gridBagConstraints2);
        
        pnlIterations.setLayout(new java.awt.GridBagLayout());
        java.awt.GridBagConstraints gridBagConstraints3;
        
        txtIterations.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.textfield.iterations.text"));
        txtIterations.setToolTipText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.textfield.iterations.tooltip"));
        gridBagConstraints3 = new java.awt.GridBagConstraints();
        gridBagConstraints3.gridx = 1;
        gridBagConstraints3.gridy = 1;
        gridBagConstraints3.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints3.insets = new java.awt.Insets(1, 1, 1, 1);
        gridBagConstraints3.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints3.weightx = 0.5;
        pnlIterations.add(txtIterations, gridBagConstraints3);
        
        progIterations.setToolTipText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.prog.iterations.tooltip"));
        progIterations.setEnabled(false);
        gridBagConstraints3 = new java.awt.GridBagConstraints();
        gridBagConstraints3.gridx = 2;
        gridBagConstraints3.gridy = 1;
        gridBagConstraints3.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints3.insets = new java.awt.Insets(1, 1, 1, 1);
        gridBagConstraints3.weightx = 1.0;
        pnlIterations.add(progIterations, gridBagConstraints3);
        
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 2;
        gridBagConstraints2.gridy = 2;
        gridBagConstraints2.gridwidth = 2;
        gridBagConstraints2.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints2.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints2.weightx = 1.0;
        pnlHost.add(pnlIterations, gridBagConstraints2);
        
        btnStartStop.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.button.startstop.starttext"));
        btnStartStop.setEnabled(false);
        btnStartStop.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                btnStartStopActionPerformed(evt);
            }
        });
        
        pnlHostButtons.add(btnStartStop);
        
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 1;
        gridBagConstraints2.gridy = 8;
        gridBagConstraints2.gridwidth = 4;
        gridBagConstraints2.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints2.weightx = 1.0;
        pnlHost.add(pnlHostButtons, gridBagConstraints2);
        
        lblInitStatus.setFont(new java.awt.Font("Dialog", 0, 12));
        lblInitStatus.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.label.initializer.status.notinitialized"));
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 2;
        gridBagConstraints2.gridy = 5;
        gridBagConstraints2.gridwidth = 2;
        gridBagConstraints2.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints2.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints2.weightx = 1.0;
        pnlHost.add(lblInitStatus, gridBagConstraints2);
        
        lblCodebase.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.label.codebase.text"));
        lblCodebase.setToolTipText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.label.codebase.tooltip"));
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 1;
        gridBagConstraints2.gridy = 3;
        gridBagConstraints2.anchor = java.awt.GridBagConstraints.WEST;
        pnlHost.add(lblCodebase, gridBagConstraints2);
        
        txtCodebase.setText(System.getProperty("user.dir"));
        txtCodebase.setToolTipText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.textfield.codebase.tooltip"));
        txtCodebase.addFocusListener(new java.awt.event.FocusAdapter()
        {
            public void focusLost(java.awt.event.FocusEvent evt)
            {
                txtCodebaseFocusLost(evt);
            }
        });
        
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 2;
        gridBagConstraints2.gridy = 3;
        gridBagConstraints2.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints2.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints2.weightx = 1.0;
        pnlHost.add(txtCodebase, gridBagConstraints2);
        
        btnBrowseCodebase.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.button.codebase-browse.text"));
        btnBrowseCodebase.setToolTipText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.button.codebase-browse.tooltip"));
        btnBrowseCodebase.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                btnBrowseCodebaseActionPerformed(evt);
            }
        });
        
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 3;
        gridBagConstraints2.gridy = 3;
        gridBagConstraints2.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints2.anchor = java.awt.GridBagConstraints.WEST;
        pnlHost.add(btnBrowseCodebase, gridBagConstraints2);
        
        pnlAdvanced.setLayout(new java.awt.GridBagLayout());
        java.awt.GridBagConstraints gridBagConstraints4;
        
        pnlAdvanced.setVisible( false );
        lblUDPPortNumber.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.advanced.label.udpportnumber.text"));
        lblUDPPortNumber.setEnabled(false);
        gridBagConstraints4 = new java.awt.GridBagConstraints();
        gridBagConstraints4.gridx = 1;
        gridBagConstraints4.gridy = 1;
        gridBagConstraints4.anchor = java.awt.GridBagConstraints.WEST;
        pnlAdvanced.add(lblUDPPortNumber, gridBagConstraints4);
        
        txtUDPPortNumber.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.advanced.textfield.udpportnumber.text"));
        txtUDPPortNumber.setEnabled(false);
        gridBagConstraints4 = new java.awt.GridBagConstraints();
        gridBagConstraints4.gridx = 2;
        gridBagConstraints4.gridy = 1;
        gridBagConstraints4.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints4.weightx = 1.0;
        pnlAdvanced.add(txtUDPPortNumber, gridBagConstraints4);
        
        lblHTTPPortNumber.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.advanced.label.httpportnumber.text"));
        lblHTTPPortNumber.setEnabled(false);
        gridBagConstraints4 = new java.awt.GridBagConstraints();
        gridBagConstraints4.gridx = 1;
        gridBagConstraints4.gridy = 2;
        gridBagConstraints4.anchor = java.awt.GridBagConstraints.WEST;
        pnlAdvanced.add(lblHTTPPortNumber, gridBagConstraints4);
        
        txtHTTPPortNumber.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.advanced.textfield.httpportnumber.text"));
        txtHTTPPortNumber.setEnabled(false);
        txtHTTPPortNumber.addFocusListener(new java.awt.event.FocusAdapter()
        {
            public void focusLost(java.awt.event.FocusEvent evt)
            {
                txtHTTPPortNumberFocusLost(evt);
            }
        });
        
        gridBagConstraints4 = new java.awt.GridBagConstraints();
        gridBagConstraints4.gridx = 2;
        gridBagConstraints4.gridy = 2;
        gridBagConstraints4.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints4.weightx = 1.0;
        pnlAdvanced.add(txtHTTPPortNumber, gridBagConstraints4);
        
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 2;
        gridBagConstraints2.gridy = 7;
        gridBagConstraints2.gridwidth = 2;
        gridBagConstraints2.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints2.insets = new java.awt.Insets(1, 1, 1, 1);
        gridBagConstraints2.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints2.weightx = 1.0;
        pnlHost.add(pnlAdvanced, gridBagConstraints2);
        
        tglAdvanced.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/coinor/opents/net/collapsed.gif")));
        tglAdvanced.setBorder(null);
        tglAdvanced.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
        tglAdvanced.setSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/org/coinor/opents/net/expanded.gif")));
        tglAdvanced.addChangeListener(new javax.swing.event.ChangeListener()
        {
            public void stateChanged(javax.swing.event.ChangeEvent evt)
            {
                tglAdvancedStateChanged(evt);
            }
        });
        
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 2;
        gridBagConstraints2.gridy = 6;
        gridBagConstraints2.anchor = java.awt.GridBagConstraints.WEST;
        pnlHost.add(tglAdvanced, gridBagConstraints2);
        
        lblAdvanced.setText(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.label.advanced.text"));
        gridBagConstraints2 = new java.awt.GridBagConstraints();
        gridBagConstraints2.gridx = 1;
        gridBagConstraints2.gridy = 6;
        gridBagConstraints2.anchor = java.awt.GridBagConstraints.WEST;
        pnlHost.add(lblAdvanced, gridBagConstraints2);
        
        gridBagConstraints1 = new java.awt.GridBagConstraints();
        gridBagConstraints1.gridx = 1;
        gridBagConstraints1.gridy = 1;
        gridBagConstraints1.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints1.weightx = 1.0;
        getContentPane().add(pnlHost, gridBagConstraints1);
        
        pnlClients.setLayout(new java.awt.BorderLayout());
        
        pnlClients.setBorder(new javax.swing.border.TitledBorder(java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.client.border.title")));
        tblClients.setModel(clientTableModel = new ClientTabuSearchTableModel());
        tblClients.addPropertyChangeListener(new java.beans.PropertyChangeListener()
        {
            public void propertyChange(java.beans.PropertyChangeEvent evt)
            {
                tblClientsPropertyChange(evt);
            }
        });
        
        scrClients.setViewportView(tblClients);
        
        pnlClients.add(scrClients, java.awt.BorderLayout.CENTER);
        
        gridBagConstraints1 = new java.awt.GridBagConstraints();
        gridBagConstraints1.gridx = 1;
        gridBagConstraints1.gridy = 2;
        gridBagConstraints1.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints1.weightx = 1.0;
        gridBagConstraints1.weighty = 1.0;
        getContentPane().add(pnlClients, gridBagConstraints1);
        
        pack();
        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setSize(new java.awt.Dimension(400, 400));
        setLocation((screenSize.width-400)/2,(screenSize.height-400)/2);
    }//GEN-END:initComponents

    private void tblClientsPropertyChange(java.beans.PropertyChangeEvent evt)//GEN-FIRST:event_tblClientsPropertyChange
    {//GEN-HEADEREND:event_tblClientsPropertyChange
        // Add your handling code here:
        System.out.println( evt );
        System.out.println( "  New value: " + evt.getNewValue() );
        System.out.println( "  Old value: " + evt.getOldValue() );
        System.out.println( "  Prop name: " + evt.getPropertyName() );
    }//GEN-LAST:event_tblClientsPropertyChange

    private void txtInitClassFocusLost(java.awt.event.FocusEvent evt)//GEN-FIRST:event_txtInitClassFocusLost
    {//GEN-HEADEREND:event_txtInitClassFocusLost
        // Add your handling code here:
        JTextField tf = (JTextField)evt.getSource();
        String text = tf.getText();
        setInitializerClassname( text );
    }//GEN-LAST:event_txtInitClassFocusLost

    private void clusterControllerTabuSearchStarted(org.coinor.opents.net.ClusterControllerEvent evt)//GEN-FIRST:event_clusterControllerTabuSearchStarted
    {//GEN-HEADEREND:event_clusterControllerTabuSearchStarted
        // Add your handling code here:
        handleTabuSearchStarted( evt );
    }//GEN-LAST:event_clusterControllerTabuSearchStarted

    private void btnStartStopActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_btnStartStopActionPerformed
    {//GEN-HEADEREND:event_btnStartStopActionPerformed
        // We're already solving, then stop. Else start
        if( clusterController.isSolving()  )
            stopTabuSearch();
        else 
            startTabuSearch();
        
    }//GEN-LAST:event_btnStartStopActionPerformed

    private void txtHTTPPortNumberFocusLost(java.awt.event.FocusEvent evt)//GEN-FIRST:event_txtHTTPPortNumberFocusLost
    {//GEN-HEADEREND:event_txtHTTPPortNumberFocusLost
        // Add your handling code here:
        JTextField tf = (JTextField)evt.getSource();
        String text = tf.getText();
        setHTTPPortNumber( new Integer(text).intValue() ); 
    }//GEN-LAST:event_txtHTTPPortNumberFocusLost

    private void txtCodebaseFocusLost(java.awt.event.FocusEvent evt)//GEN-FIRST:event_txtCodebaseFocusLost
    {//GEN-HEADEREND:event_txtCodebaseFocusLost
        // Add your handling code here:
        JTextField tf = (JTextField)evt.getSource();
        String text = tf.getText();
        setCodebase( text );
    }//GEN-LAST:event_txtCodebaseFocusLost

private void tglAdvancedStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tglAdvancedStateChanged
    if( evt.getSource() == tglAdvanced )
    {
        pnlAdvanced.setVisible( tglAdvanced.isSelected() );
    }   // end if: toggle advanced
}//GEN-LAST:event_tglAdvancedStateChanged

private void btnBrowseCodebaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnBrowseCodebaseActionPerformed
    // Get existing value for codebase
    String codebase = txtCodebase.getText();
    JFileChooser chooser = new JFileChooser( codebase );
    chooser.setFileSelectionMode( chooser.DIRECTORIES_ONLY );
    int result = chooser.showOpenDialog( this );
    if( result == chooser.APPROVE_OPTION )
    {
        txtCodebase.setText( chooser.getCurrentDirectory().toString() );
        setCodebase( chooser.getCurrentDirectory().toString() );
    }   // end if: new directory

}//GEN-LAST:event_btnBrowseCodebaseActionPerformed

    /** Exit the Application */
    private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
        saveSettings();
        System.exit(0);
    }//GEN-LAST:event_exitForm

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) 
    {
        //ClusterController.initSecurity();
        
        try{
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } 
        catch(Exception e) {
            System.out.println("Error setting native LAF: " + e);
        }

        ClusterApp app = new ClusterApp();
        app.show();
   /*     
        try{
            app.start();
        }   // end try
        catch(IOException e ){e.printStackTrace();}
    */
    }


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private org.coinor.opents.net.ClusterController clusterController;
    private org.coinor.opents.net.ClientTabuSearchTableModel clientTableModel;
    private javax.swing.JPanel pnlHost;
    private javax.swing.JLabel lblTSName;
    private javax.swing.JLabel lblTSNameValue;
    private javax.swing.JLabel lblInitClass;
    private javax.swing.JTextField txtInitClass;
    private javax.swing.JButton btnClassBrowse;
    private javax.swing.JLabel lblIterations;
    private javax.swing.JPanel pnlIterations;
    private javax.swing.JTextField txtIterations;
    private javax.swing.JProgressBar progIterations;
    private javax.swing.JPanel pnlHostButtons;
    private javax.swing.JButton btnStartStop;
    private javax.swing.JLabel lblInitStatus;
    private javax.swing.JLabel lblCodebase;
    private javax.swing.JTextField txtCodebase;
    private javax.swing.JButton btnBrowseCodebase;
    private javax.swing.JPanel pnlAdvanced;
    private javax.swing.JLabel lblUDPPortNumber;
    private javax.swing.JTextField txtUDPPortNumber;
    private javax.swing.JLabel lblHTTPPortNumber;
    private javax.swing.JTextField txtHTTPPortNumber;
    private javax.swing.JToggleButton tglAdvanced;
    private javax.swing.JLabel lblAdvanced;
    private javax.swing.JPanel pnlClients;
    private javax.swing.JScrollPane scrClients;
    private javax.swing.JTable tblClients;
    // End of variables declaration//GEN-END:variables

    
    
/* Everything below this I added, not Forte */
    
    
    private Initializer initializer;
    
    
    private void initPostForteComponents()
    {
        loadSettings();
        clientTableModel.setClusterController( clusterController );
    }   // end initPostForteComponents
    
     
    
    private void setCodebase( String codebase )
    {
        System.out.println( "Setting codebase to " + codebase );
        try{
            clusterController.setTabuSearchCodebase( codebase );
            txtCodebase.setText( codebase );
        }   // end try
        catch( IOException e ){
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, e.getLocalizedMessage() );
        }   // end catch
        updateStartStopButton();
    }   // end setCodebase
    
    
    private String getCodebase()
    {
        return txtCodebase.getText();
    }   // end getCodebase
    
    
    
    private void setHTTPPortNumber( int port )
    {
  /*      
        try{
            classServer.setPort( port );
        }   // end try
        catch( IOException e ){
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, e.getLocalizedMessage() );
        }   // end catch
   */
        updateStartStopButton();
    }   // end setHTTPPortNumber
    
    
    private void startCodebaseServer()
    {
 /*       
        try{
            classServer.start();
        }   // end try
        catch( IOException e ){
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, e.getLocalizedMessage() );
        }   // end catch
  */
    }   // end startCodebaseServer
    
    
    private void setInitializerClassname( String classname )
    {
        txtInitClass.setText( classname );
        updateStartStopButton();
    }   // end setInitializerClassname
    
    
    private String getInitializerClassname()
    {
        return txtInitClass.getText();
    }   // end getInitializerClassname
    
    
    
    private Initializer getInitializer()
    {
        if( initializer == null ){
            try{
                URL[] urls = new URL[]{ new File( txtCodebase.getText() ).toURL() };
                ClassLoader cl = new URLClassLoader( urls );
                Class c = cl.loadClass( txtInitClass.getText() );
                if( org.coinor.opents.net.Initializer.class.isAssignableFrom( c ) ){
                    initializer = (Initializer)c.newInstance();
                }   // end if: is an Initializer
            }   // end try
            catch( Exception e ){
                e.printStackTrace();
                return null;
            }   // end catch
        }   // end if: need new initializer
        
        if( initializer == null )
            return null;
        
        java.awt.Component cust = initializer.getCustomizer();
        if( cust != null )
            JOptionPane.showMessageDialog( this, cust );
        if( !initializer.initialize( cust ) )
            return null;
        
        return initializer;
    }   // end getInitializer
    
    
    private int getIterations()
    {
        int iters = 1000;
        try{
            iters = new Integer( txtIterations.getText() ).intValue();
        }   // end try
        catch( Exception e ){
            e.printStackTrace();
            txtIterations.setText( new Integer( iters ).toString() );
        }   // end catch
        return iters;
    }   // end getIterations
    
    
    private void setIterations( int iters )
    {
        txtIterations.setText( new Integer( iters ).toString() );
    }   // end setIterations
    
    
    private void loadSettings()
    {
        String home = System.getProperty( "user.home" );
        System.out.println( "Home: " + home );
        java.io.File file = new java.io.File( home, ".opents_cluster_app" );
        java.util.Properties prop = new java.util.Properties();
        
        java.io.InputStream in = null;
        try{
            in = new java.io.BufferedInputStream(
                 new java.io.FileInputStream( file ) );
            prop.load( in );
        }   // end try
        catch( IOException e ){
            e.printStackTrace();
        }   // end catch
        finally{
            try{ in.close(); }
            catch( Exception e ){}
        }   // end finally
        
        String codebase  = prop.getProperty( "user.codebase" );
        String initClass = prop.getProperty( "user.initializer-class" );
        String iters     = prop.getProperty( "user.iterations" );
        
        if( codebase != null )
            setCodebase( codebase );
        
        if( initClass != null )
            setInitializerClassname( initClass );
        
        if( iters != null ){
            try{
                setIterations( new Integer( iters ).intValue() );
            }   // end catch
            catch( Exception e ){
                e.printStackTrace();
            }   // end catch
        }   // end if: iters
        
    }   // end loadSettings
    
    
    private void saveSettings()
    {
        String home = System.getProperty( "user.home" );
        System.out.println( "Home: " + home );
        java.io.File file = new java.io.File( home, ".opents_cluster_app" );
        java.util.Properties prop = new java.util.Properties();
        
        prop.put( "user.codebase", txtCodebase.getText() );
        prop.put( "user.initializer-class", txtInitClass.getText() );
        prop.put( "user.iterations", txtIterations.getText() );
        
        java.io.OutputStream out = null;
        try{
            out = new java.io.BufferedOutputStream(
                  new java.io.FileOutputStream( file ) );
            prop.store(out, "OpenTS Cluster App Settings" );
        }   // end try
        catch( IOException e ){
            e.printStackTrace();
        }   // end catch
        finally{
            try{ out.close(); }
            catch( Exception e ){}
        }   // end finally
    }   // end saveSettings
    
    
    
    private synchronized void startTabuSearch()
    {
        if( clusterController.isSolving() )
            return; // Already running
        
        JButton btn = btnStartStop;
        JProgressBar prog = progIterations;
        btn.setEnabled( false );
        prog.setEnabled( true );

        // JDK 1.4 only
        try{
            prog.setIndeterminate( true );
        }   // end
        catch( Exception e ){}

        initializer = getInitializer();
        
        if( initializer == null ){
            JOptionPane.showMessageDialog( this, "Unsuccessful" );
            btn.setEnabled( true );
            return;
        }   // end if: unsuccessful

        clusterController.startSolving( initializer, getIterations() );
        
        updateStartStopButton();
    }   // end startTabuSearch
    
    
    
    private synchronized void stopTabuSearch()
    {
        if( !clusterController.isSolving() )
            return; // Already stopped
        
        JButton btn = btnStartStop;
        JProgressBar prog = progIterations;
        
        btn.setEnabled( false );
        
        clusterController.stopSolving();
    }   // end stopTabuSearch
    
    
    
    private void updateStartStopButton()
    {
        // Solving?
        if( clusterController.isSolving() ){
            
            // Set up button for "stop"
            btnStartStop.setText( java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.button.startstop.stoptext") );
            btnStartStop.setEnabled( true );
            
        }   // end if: solving
        
        // Else, not solving
        else{
            
            // Got codebase and initializer class?
            if( getCodebase() != null && !getCodebase().equals("") &&
            getInitializerClassname() != null && !getInitializerClassname().equals("") ){
                
                // Set up button for "start"
                btnStartStop.setText( java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.button.startstop.starttext") );
                btnStartStop.setEnabled( true );
            
            }   // end if: got fields
            else{
                // Set up button for "start"
                btnStartStop.setText( java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.button.startstop.starttext") );
                btnStartStop.setEnabled( false );
            }   // end else: some fields missing
            
        }   // end else: not solving
        
    }   // end updateStartStopButton
    
    
    
    
/* ******** T A B U   S E A R C H   H A N D L E R S  ******** */    
    
    
    
    
    
    private void handleTabuSearchStarted( ClusterControllerEvent evt )
    {
        final TabuSearch tabuSearch = evt.getTabuSearch();
        // Listeners
        tabuSearch.addTabuSearchListener( new TabuSearchAdapter(){

            public void tabuSearchStopped( TabuSearchEvent evt ){
                handleTabuSearchStopped( evt );
            }   // end tabuSearchStopped

            public void newCurrentSolutionFound( TabuSearchEvent evt ){
                handleNewCurrentSolutionFound( evt );
            }   // end newCurrentSolutionFound
        });
        
        SwingUtilities.invokeLater( new Runnable(){
            public void run(){
                JProgressBar prog = progIterations;
                
                // JDK 1.4 only
                try{
                    prog.setIndeterminate( false );
                }   // end
                catch( Exception e ){}
                
                int itersCompl    = tabuSearch.getIterationsCompleted();
                int itersToGo     = tabuSearch.getIterationsToGo();
                prog.setMaximum( itersCompl + itersToGo );              
                prog.setEnabled( true );
            }   // end run
        }); // end runnable
    }   // end handleTabuSearchStarted
    
    
    
    private void handleTabuSearchStopped( TabuSearchEvent evt )
    {
        final TabuSearch ts = evt.getTabuSearch();
        SwingUtilities.invokeLater( new Runnable(){
            public void run(){
                JProgressBar prog = progIterations;

                System.out.println( "Tabu search stopped." );
                System.out.println( "Best solution: " + ts.getBestSolution() );

                initializer.setBestSolution( ts.getBestSolution() );
                
                prog.setValue( 0 );
                prog.setEnabled( false );
                btnStartStop.setText( java.util.ResourceBundle.getBundle("org/coinor/opents/net/strings").getString("panel.host.button.startstop.starttext") );
                btnStartStop.setEnabled( true );
            }   // end run
        }); // end runnable
    }   // end handleTabuSearchStopped
    
    
    private void handleNewCurrentSolutionFound( TabuSearchEvent evt )
    {
        HostTabuSearch ts       = (HostTabuSearch)evt.getTabuSearch();
        final JProgressBar Prog = progIterations;
        final int ItersCompl    = ts.getIterationsCompleted();
        final int ItersToGo     = ts.getIterationsToGo();
        int progMax             = Prog.getMaximum();
        
        // Fix upper limit in case someone changed it.
        if( progMax != ItersCompl + ItersToGo ){
            final int ProgMax = progMax = ItersCompl + ItersToGo;
            SwingUtilities.invokeLater( new Runnable(){
                public void run(){
                    Prog.setMaximum( ProgMax );
                }   // end run
            }); // end runnable
        }   // end if
        
        // Only update the progress bar periodically
        if( (progMax <= 100) || ((ItersCompl % (progMax / 100) ) == 0) ){
            SwingUtilities.invokeLater( new Runnable(){
                public void run(){
                    Prog.setValue( ItersCompl );
                }   // end run
            }); // end runnable
        }   // end if
        
        
    }   // end handleNewCurrentSolution
    
    
    
    
}
